home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / n_append.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  14.3 KB  |  479 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *      append.c
  4.  *      
  5.  *   DESCRIPTION
  6.  *      routines to handle append nodes.
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *      ExecInitAppend  - initialize the append node
  10.  *      ExecProcAppend  - retrieve the next tuple from the node
  11.  *      ExecEndAppend   - shut down the append node
  12.  *
  13.  *   NOTES
  14.  *      Each append node contains a list of one or more subplans which
  15.  *      must be iteratively processed (forwards or backwards).
  16.  *      Tuples are retrieved by executing the 'whichplan'th subplan
  17.  *      until the subplan stops returning tuples, at which point that
  18.  *      plan is shut down and the next started up.
  19.  *
  20.  *      Append nodes don't make use of their left and right
  21.  *      subtrees, rather they maintain a list of subplans so
  22.  *      a typical append node looks like this in the plan tree:
  23.  *
  24.  *                 ...
  25.  *                 /
  26.  *              Append -------+------+------+--- nil
  27.  *              /   \         |      |      |
  28.  *            nil   nil      ...    ...    ...
  29.  *                               subplans
  30.  *
  31.  *      Append nodes are currently used to support inheritance
  32.  *      queries, where several relations need to be scanned.
  33.  *      For example, in our standard person/student/employee/student-emp
  34.  *      example, where student and employee inherit from person
  35.  *      and student-emp inherits from student and employee, the
  36.  *      query:
  37.  *
  38.  *              retrieve (e.name) from e in person*
  39.  *
  40.  *      generates the plan:
  41.  *
  42.  *                |
  43.  *              Append -------+-------+--------+--------+
  44.  *              /   \         |       |        |        |
  45.  *            nil   nil      Scan    Scan     Scan     Scan
  46.  *                            |       |        |        |
  47.  *                          person employee student student-emp
  48.  *
  49.  *
  50.  *   IDENTIFICATION
  51.  *      $Header: /private/postgres/src/executor/RCS/n_append.c,v 1.11 1992/08/25 17:48:18 mer Exp $
  52.  * ----------------------------------------------------------------
  53.  */
  54.  
  55. #include "executor/executor.h"
  56.  
  57.  RcsId("$Header: /private/postgres/src/executor/RCS/n_append.c,v 1.11 1992/08/25 17:48:18 mer Exp $");
  58. /* ----------------------------------------------------------------
  59.  *      exec-append-initialize-next
  60.  *    
  61.  *      Sets up the append node state (i.e. the append state node)
  62.  *      for the "next" scan.
  63.  *    
  64.  *      Returns t iff there is a "next" scan to process.
  65.  * ----------------------------------------------------------------
  66.  */
  67. /**** xxref:
  68.  *           ExecInitAppend
  69.  *           ExecProcAppend
  70.  ****/
  71. List
  72. exec_append_initialize_next(node)
  73.     Append      node;
  74. {
  75.     EState         estate;
  76.     AppendState    unionstate;
  77.     TupleTableSlot result_slot;
  78.     List           rangeTable;
  79.     
  80.     int            whichplan;
  81.     int            nplans;
  82.     List           rtentries;
  83.     List           rtentry;
  84.     
  85.     Index          unionrelid;
  86.     
  87.     /* ----------------
  88.      *  get information from the append node
  89.      * ----------------
  90.      */
  91.     estate =    (EState) get_state((Plan) node);
  92.     unionstate =         get_unionstate(node);
  93.     result_slot =        get_cs_ResultTupleSlot((CommonState) unionstate);
  94.     rangeTable =         get_es_range_table(estate);
  95.     
  96.     whichplan = get_as_whichplan(unionstate);
  97.     nplans =    get_as_nplans(unionstate);
  98.     rtentries = get_unionrtentries(node);
  99.     
  100.     if (whichplan < 0) {
  101.         /* ----------------
  102.          *      if scanning in reverse, we start at
  103.          *      the last scan in the list and then
  104.          *      proceed back to the first.. in any case
  105.          *      we inform ExecProcAppend that we are
  106.          *      at the end of the line by returning LispNil
  107.          * ----------------
  108.          */
  109.         set_as_whichplan(unionstate, 0);
  110.         return LispNil;
  111.     
  112.     } else if (whichplan >= nplans) {
  113.         /* ----------------
  114.          *      as above, end the scan if we go beyond
  115.          *      the last scan in our list..
  116.          * ----------------
  117.          */
  118.         set_as_whichplan(unionstate, nplans - 1);
  119.         return LispNil;
  120.         
  121.     } else {
  122.         /* ----------------
  123.          *      initialize the scan
  124.          *      (and update the range table appropriately)
  125.          * ----------------
  126.          */
  127.     if (get_unionrelid(node) > 0) {
  128.         rtentry = nth(whichplan, rtentries);
  129.         if (lispNullp(rtentry))
  130.         elog(DEBUG, "exec_append_initialize_next: rtentry is nil");
  131.       
  132.         unionrelid = get_unionrelid(node);
  133.         rt_store(unionrelid, rangeTable, rtentry);
  134.         if (get_es_junkFilter_list(estate)) {
  135.         set_es_junkFilter(estate,
  136.             (JunkFilter)nth(whichplan, get_es_junkFilter_list(estate)));
  137.         }
  138.         if (get_es_result_relation_info_list(estate)) {
  139.         set_es_result_relation_info(estate,
  140.             (RelationInfo)nth(whichplan,
  141.                      get_es_result_relation_info_list(estate)));
  142.         }
  143.         set_ttc_whichplan( result_slot, whichplan );
  144.     }
  145.       
  146.     return LispTrue;
  147.     }
  148. }
  149.  
  150. /* ----------------------------------------------------------------
  151.  *      ExecInitAppend
  152.  *    
  153.  *      Begins all of the subscans of the append node, storing the
  154.  *      scan structures in the 'initialized' vector of the append-state
  155.  *      structure.
  156.  *
  157.  *     (This is potentially wasteful, since the entire result of the
  158.  *      append node may not be scanned, but this way all of the
  159.  *      structures get allocated in the executor's top level memory
  160.  *      block instead of that of the call to ExecProcAppend.)
  161.  *    
  162.  *      Returns the scan result of the first scan.
  163.  * ----------------------------------------------------------------
  164.  */
  165. /**** xxref:
  166.  *           ExecInitNode
  167.  ****/
  168. List
  169. ExecInitAppend(node, estate, parent)
  170.     Append      node;
  171.     EState      estate;
  172.     Plan     parent;
  173. {
  174.     AppendState unionstate;
  175.     List        rangeTable;     /* LLL unused */
  176.     
  177.     int         nplans;
  178.     List        rtentries;
  179.     List        unionplans;
  180.     ListPtr     initialized;
  181.     int         i;
  182.     Plan        initNode;
  183.     List        result;
  184.     List        junkList;
  185.     int         baseid;
  186.     RelationInfo es_rri = get_es_result_relation_info(estate);
  187.     
  188.     /* ----------------
  189.      *  assign execution state to node and get information
  190.      *  for append state
  191.      * ----------------
  192.      */
  193.     set_state((Plan) node,  (EStatePtr)estate);
  194.     
  195.     unionplans =        get_unionplans(node);
  196.     nplans =            length(unionplans);
  197.     rtentries =         get_unionrtentries(node);
  198.     
  199.     CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
  200.     initialized = (ListPtr)
  201.         palloc(nplans * sizeof(List));
  202.     
  203.     /* ----------------
  204.      *  create new AppendState for our append node
  205.      * ----------------
  206.      */   
  207.     unionstate =  MakeAppendState(0, nplans, initialized, rtentries);
  208.     set_unionstate(node, unionstate);
  209.     
  210.     /* ----------------
  211.      *  Miscellanious initialization
  212.      *
  213.      *         +    assign node's base_id
  214.      *       +    assign debugging hooks
  215.      *
  216.      *  Append plans don't have expression contexts because they
  217.      *  never call ExecQual or ExecTargetList.
  218.      * ----------------
  219.      */
  220.     ExecAssignNodeBaseInfo(estate, (BaseNode) unionstate, parent);
  221.     ExecAssignDebugHooks((Plan) node, (BaseNode) unionstate);
  222.  
  223. #define APPEND_NSLOTS 1
  224.     /* ----------------
  225.      *    append nodes still have Result slots, which hold pointers
  226.      *  to tuples, so we have to initialize them..
  227.      * ----------------
  228.      */
  229.     ExecInitResultTupleSlot(estate, (CommonState) unionstate);
  230.     
  231.     /*
  232.      * If the inherits rtentry is the result relation, we have to make
  233.      * a result relation info list for all inheritors so we can update
  234.      * their indices and put the result tuples in the right place etc.
  235.      *
  236.      * e.g. replace p (age = p.age + 1) from p in person*
  237.      */
  238.     if ((es_rri != (RelationInfo)NULL) &&
  239.     (get_unionrelid((Append)node) == get_ri_RangeTableIndex(es_rri)))
  240.     {
  241.     RelationInfo rri;
  242.     List         resultList = LispNil;
  243.     List         rtentryP;
  244.  
  245.     foreach(rtentryP,rtentries)
  246.     {
  247.         ObjectId reloid;
  248.         List     rtentry = CAR(rtentryP);
  249.  
  250.         reloid = CInteger(rt_relid(rtentry));
  251.         rri = MakeRelationInfo(get_ri_RangeTableIndex(es_rri),
  252.                    heap_open(reloid),
  253.                    0,        /* num indices */
  254.                    NULL,    /* index descs */
  255.                    NULL);    /* index key info */
  256.         resultList = nappend1(resultList, (LispValue)rri);
  257.         ExecOpenIndices(reloid, rri);
  258.     }
  259.     set_es_result_relation_info_list(estate, resultList);
  260.     }
  261.     /* ----------------
  262.      *  call ExecInitNode on each of the plans in our list
  263.      *  and save the results into the array "initialized"
  264.      * ----------------
  265.      */       
  266.     junkList = LispNil;
  267.     for(i = 0; i < nplans ; i++ ) {
  268.     JunkFilter j;
  269.     List       targetList;
  270.         /* ----------------
  271.          *  NOTE: we first modify range table in 
  272.          *        exec_append_initialize_next() and
  273.          *        then initialize the subnode,
  274.          *        since it may use the range table.
  275.          * ----------------
  276.          */
  277.         set_as_whichplan(unionstate, i);
  278.         exec_append_initialize_next(node);
  279.     
  280.         initNode = (Plan) nth(i, unionplans);
  281.         result =          ExecInitNode(initNode, estate, (Plan) node);
  282.     
  283.         initialized[i] = result;
  284.     
  285.     /* ---------------
  286.      *  Each targetlist in the subplan may need its own junk filter
  287.      *
  288.      *  This is true only when the reln being replaced/deleted is
  289.      *  the one that we're looking at the subclasses of
  290.      * ---------------
  291.      */
  292.     if ((es_rri != (RelationInfo)NULL) &&
  293.         (get_unionrelid((Append)node) == get_ri_RangeTableIndex(es_rri))) {
  294.  
  295.         targetList = get_qptargetlist(initNode);
  296.         j = (JunkFilter) ExecInitJunkFilter(targetList);
  297.         junkList = nappend1(junkList, (LispValue)j);
  298.     }
  299.  
  300.     }
  301.     set_es_junkFilter_list(estate, junkList);
  302.     if (junkList != LispNil)
  303.     set_es_junkFilter(estate, (JunkFilter)CAR(junkList));
  304.     
  305.     /* ----------------
  306.      *    initialize the return type from the appropriate subplan.
  307.      * ----------------
  308.      */
  309.     initNode = (Plan) nth(0, unionplans);
  310.     ExecAssignResultType((CommonState) unionstate,
  311.              ExecGetExecTupDesc(initNode),
  312.              ExecGetTupType(initNode));
  313.     set_cs_ProjInfo((CommonState) unionstate, NULL);
  314.     
  315.     /* ----------------
  316.      *  return the result from the first subplan's initialization
  317.      * ----------------
  318.      */       
  319.     set_as_whichplan(unionstate, 0);
  320.     exec_append_initialize_next(node);
  321.     result = (List) initialized[0];
  322.     
  323.     return
  324.         result;
  325. }
  326.  
  327. int
  328. ExecCountSlotsAppend(node)
  329.     Plan node;
  330. {
  331.     List plan;
  332.     List unionplans = get_unionplans((Append)node);
  333.     int  nSlots     = 0;
  334.  
  335.     foreach (plan,unionplans) {
  336.     nSlots += ExecCountSlotsNode(CAR(plan));
  337.     }
  338.     return nSlots + APPEND_NSLOTS;
  339. }
  340.  
  341. /* ----------------------------------------------------------------
  342.  *     ExecProcAppend
  343.  *    
  344.  *      Handles the iteration over the multiple scans.
  345.  *    
  346.  *     NOTE: Can't call this ExecAppend, that name is used in execMain.l
  347.  * ----------------------------------------------------------------
  348.  */
  349. /**** xxref:
  350.  *           ExecProcAppend
  351.  *           ExecProcNode
  352.  ****/
  353. TupleTableSlot
  354. ExecProcAppend(node)
  355.     Append              node;
  356. {
  357.     EState              estate;
  358.     AppendState         unionstate;
  359.     
  360.     int                 whichplan;
  361.     List                unionplans;
  362.     Plan                subnode;
  363.     TupleTableSlot      result;
  364.     TupleTableSlot      result_slot;
  365.     ScanDirection       direction;
  366.     
  367.     /* ----------------
  368.      *  get information from the node
  369.      * ----------------
  370.      */
  371.     unionstate =      get_unionstate(node);
  372.     estate = (EState) get_state((Plan) node);
  373.     direction =       get_es_direction(estate);
  374.     
  375.     unionplans =      get_unionplans(node);
  376.     whichplan =       get_as_whichplan(unionstate);
  377.     result_slot =     get_cs_ResultTupleSlot((CommonState) unionstate);
  378.     
  379.     /* ----------------
  380.      *  figure out which subplan we are currently processing
  381.      * ----------------
  382.      */
  383.     subnode = (Plan) nth(whichplan, unionplans);
  384.     
  385.     if (lispNullp(subnode))
  386.         elog(DEBUG, "ExecProcAppend: subnode is NULL");
  387.     
  388.     /* ----------------
  389.      *  get a tuple from the subplan
  390.      * ----------------
  391.      */
  392.     result = ExecProcNode(subnode);
  393.     
  394.     if (! TupIsNull((Pointer) result)) {
  395.         /* ----------------
  396.          *  if the subplan gave us something then place a copy of
  397.      *  whatever we get into our result slot and return it, else..
  398.          * ----------------
  399.          */
  400.     return
  401.         (TupleTableSlot)ExecStoreTuple(ExecFetchTuple((Pointer) result),
  402.                        (Pointer) result_slot,
  403.                            ExecSlotBuffer((Pointer) result),
  404.                            false);
  405.     
  406.     } else {
  407.         /* ----------------
  408.          *  .. go on to the "next" subplan in the appropriate
  409.          *  direction and try processing again (recursively)
  410.          * ----------------
  411.          */
  412.         whichplan = get_as_whichplan(unionstate);
  413.         
  414.         if (direction == EXEC_FRWD)
  415.     {
  416.             set_as_whichplan(unionstate, whichplan + 1);
  417.     }
  418.         else
  419.     {
  420.             set_as_whichplan(unionstate, whichplan - 1);
  421.     }
  422.  
  423.     /* ----------------
  424.      *  return something from next node or an empty slot
  425.      *  all of our subplans have been exhausted.
  426.      * ----------------
  427.      */
  428.         if (exec_append_initialize_next(node)) {
  429.         ExecSetSlotDescriptorIsNew((Pointer) result_slot, true);
  430.             return
  431.         ExecProcAppend(node);
  432.         } else
  433.         return
  434.         (TupleTableSlot)ExecClearTuple((Pointer) result_slot);
  435.     }
  436. }
  437.  
  438. /* ----------------------------------------------------------------
  439.  *      ExecEndAppend
  440.  *    
  441.  *      Shuts down the subscans of the append node.
  442.  *    
  443.  *      Returns nothing of interest.
  444.  * ----------------------------------------------------------------
  445.  */
  446. /**** xxref:
  447.  *           ExecEndNode
  448.  ****/
  449. void
  450. ExecEndAppend(node)
  451.     Append      node;
  452. {
  453.     AppendState unionstate;
  454.     int         nplans;
  455.     List        unionplans;
  456.     ListPtr     initialized;
  457.     int         i;
  458.     
  459.     /* ----------------
  460.      *  get information from the node
  461.      * ----------------
  462.      */
  463.     unionstate =  get_unionstate(node);
  464.     unionplans =  get_unionplans(node);
  465.     nplans =      get_as_nplans(unionstate);
  466.     initialized = get_as_initialized(unionstate);
  467.     
  468.     /* ----------------
  469.      *  shut down each of the subscans
  470.      * ----------------
  471.      */
  472.     for(i = 0; i < nplans; i++) {
  473.         if (! lispNullp(initialized[i])) {
  474.             ExecEndNode( (Plan) nth(i, unionplans) );
  475.         }
  476.     }
  477. }
  478.  
  479.